AWS Serverless Application Model(SAM)で、AWS Lambda関数とAmazon API Gatawayをデプロイしてみた

AWS Serverless Application Model(SAM)で、AWS Lambda関数とAmazon API Gatawayをデプロイしてみた

AWS Serverless Application Model(SAM)を使用して、AWS LambdaとAmazon API Gatawayをデプロイします。PythonによるLambdaコードもSAM経由でデプロイして、サーバーレスなAPIアプリケーションを構築します。
Clock Icon2024.08.13

AWS LambdaをIaCで管理したい

おのやんです。

みなさん、AWS Lambda(以下、Lambda)をコードで管理したいと思ったことはありませんか?私はあります。

AWSインフラをコードで管理することは、一般的にInfrastructure as Code(以下、IaC)と呼ばれる運用管理手法のひとつです。AWSをIaCで管理する際は、AWS CloudFormationやAWS CDK、Terraformなどの選択肢があります。

そんなIaCですが、Lambdaなどインフラリソースとプログラムのコードが密接に関連しているリソースの場合、インフラリソースだけでなくコードも一緒に管理したい場面があります。そんな場合は、 AWS Serverless Application Model(以下、SAM) が候補に上がっていきます。

このSAMを用いて、今回Lambdaを実装する機会がありましたので、今回はそちらを紹介していきます。

SAMとは

SAMは、サーバーレスアプリケーションをIaCで管理できるフレームワークです。SAMのテンプレートはCloudFormation テンプレートの拡張版になっていて、LambdaやAPI Gatewayなどのインフラリソースに加えて、アプリケーションコードなども一緒にデプロイできます。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html

準備

前提として、AWS CLIのインストール・認証設定が済んでいる必要があります。こちらの設定を済ませておきます。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

上記が設定されている状態で、SAMを用いてリソースをデプロイする時に必要になるAWS SAM CLI(以下、SAM CLI)をインストールします。詳細はこちらの公式ドキュメントに掲載されているので、参考にしてください。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html

私は今回MacでSAM CLIをインストールする必要があったため、公式ドキュメントにならってPKGファイルをダウンロードして展開しています(執筆時点で、Homebrewによるインストールは公式ドキュメントに書かれていないため注意してください)。

ローカル環境での動作確認

それでは、実際に構築していきます。今回のディレクトリ構成は以下のようになります。

aws-test-sam-sample/
│── template.yaml
└── hello_world/
    └── app.py

template.yamlの内容は以下の通りです。AWS::Serverless::Functionの設定でLambda関数が作成され、そのコードとしてhello_world内のapp.pyが参照されます。またEventsの項目で設定しているType: Apiにより、Amazon API Gateway(以下、API Gateway)が自動で作成されます。

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Hello World API

#---------------------------------------------#
# Lambda function
#---------------------------------------------#

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9

      #---------------------------------------------#
      # API gateway
      #---------------------------------------------#

      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

この状態でsam local start-apiコマンドを実行することで、ローカルでAPIをテストできます。

% sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]                                                              
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on
your functions, changes will be reflected instantly/automatically. If you used sam build before running local commands, you   
will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM    
template                                                                                                                      
2024-08-13 11:26:54 WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:3000
2024-08-13 11:26:54 Press CTRL+C to quit

ローカルでサーバーが起動できたら、上記のアドレスにテンプレートで指定したPathを繋げたhttp://127.0.0.1:3000/helloや、http://localhost:3000/helloにブラウザからアクセスすることで、リクエストを送信できます。

requesting_api

AWS環境へのデプロイ

この動作確認ができたら、AWS環境へ実際にデプロイしてみましょう。

SAM経由でAWSにデプロイするには、まずビルドを行います。

% sam build

Building codeuri: /Users/xxx/aws-test-sam-sample/hello_world runtime: python3.9 metadata: {} architecture:   
x86_64 functions: HelloWorldFunction                                                                                          
requirements.txt file not found. Continuing the build without dependencies.                                                   
 Running PythonPipBuilder:CopySource                                                                                          

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided

ビルドが正常に終了すると、ルートディレクトリに.aws-samディレクトリが作成されます。この中に、デプロイの際に必要なアプリケーションのビルドアーティファクト(ソースコードやテンプレートファイル、デプロイ設定ファイルなど)が作成されています。

ビルドが完了したら、デブロイを実行します。アプリケーションを初めてデプロイする場合は、sam deploy --guidedを使用してデプロイ設定を構成します。2回目以降のデプロイ時は、sam deployでOKです。

デプロイログが結構な量表示されるので、トグル下に入れています。

デプロイログ
% sam deploy --guided

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: aws-test-sam-sample
        AWS Region [ap-northeast-1]: ap-northeast-1
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: Y
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [y/N]: y
        HelloWorldFunction has no authentication. Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: Y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

        Looking for resources needed for deployment:
        Creating the required resources...
        Successfully created!

        Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxx
        A different default S3 bucket can be set in samconfig.toml and auto resolution of buckets turned off by setting resolve_s3=False

        Saved arguments to config file
        Running 'sam deploy' for future deployments will use the parameters saved above.
        The above parameters can be changed by modifying samconfig.toml
        Learn more about samconfig.toml syntax at 
        https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

        Uploading to aws-test-sam-sample/xxxx  237 / 237  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : aws-test-sam-sample
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Disable rollback             : True
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-xxx
        Capabilities                 : ["CAPABILITY_IAM"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================

        Uploading to aws-test-sam-sample/xxxx.template  562 / 562  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------
Operation                      LogicalResourceId              ResourceType                   Replacement                  
-------------------------------------------------------------------------------------------------------------------------
+ Add                          HelloWorldFunctionHelloWorld   AWS::Lambda::Permission        N/A                          
                               PermissionProd                                                                             
+ Add                          HelloWorldFunctionRole         AWS::IAM::Role                 N/A                          
+ Add                          HelloWorldFunction             AWS::Lambda::Function          N/A                          
+ Add                          ServerlessRestApiDeployment4   AWS::ApiGateway::Deployment    N/A                          
                               xxxx                                                                                  
+ Add                          ServerlessRestApiProdStage     AWS::ApiGateway::Stage         N/A                          
+ Add                          ServerlessRestApi              AWS::ApiGateway::RestApi       N/A                          
-------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:123456:changeSet/samcli-deploy123459/xxx-xxx-xxx

Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2024-08-13 12:20:25 - Waiting for stack create/update to complete

CloudFormation events from stack operations (refresh every 5.0 seconds)
-------------------------------------------------------------------------------------------------------------------------
ResourceStatus                 ResourceType                   LogicalResourceId              ResourceStatusReason         
-------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS             AWS::CloudFormation::Stack     aws-test-sam-sample            User Initiated               
CREATE_IN_PROGRESS             AWS::IAM::Role                 HelloWorldFunctionRole         -                            
CREATE_IN_PROGRESS             AWS::IAM::Role                 HelloWorldFunctionRole         Resource creation Initiated  
CREATE_COMPLETE                AWS::IAM::Role                 HelloWorldFunctionRole         -                            
CREATE_IN_PROGRESS             AWS::Lambda::Function          HelloWorldFunction             -                            
CREATE_IN_PROGRESS             AWS::Lambda::Function          HelloWorldFunction             Resource creation Initiated  
CREATE_IN_PROGRESS             AWS::Lambda::Function          HelloWorldFunction             Eventual consistency check   
                                                                                             initiated                    
CREATE_IN_PROGRESS             AWS::ApiGateway::RestApi       ServerlessRestApi              -                            
CREATE_IN_PROGRESS             AWS::ApiGateway::RestApi       ServerlessRestApi              Resource creation Initiated  
CREATE_COMPLETE                AWS::ApiGateway::RestApi       ServerlessRestApi              -                            
CREATE_IN_PROGRESS             AWS::ApiGateway::Deployment    ServerlessRestApiDeployment4   -                            
                                                              xxxxxx                                                   
CREATE_IN_PROGRESS             AWS::Lambda::Permission        HelloWorldFunctionHelloWorld   -                            
                                                              xxxxxx                                              
CREATE_IN_PROGRESS             AWS::Lambda::Permission        HelloWorldFunctionHelloWorld   Resource creation Initiated  
                                                              PermissionProd                                              
CREATE_COMPLETE                AWS::Lambda::Function          HelloWorldFunction             -                            
CREATE_COMPLETE                AWS::Lambda::Permission        HelloWorldFunctionHelloWorld   -                            
                                                              PermissionProd                                              
CREATE_IN_PROGRESS             AWS::ApiGateway::Deployment    ServerlessRestApiDeployment4   Resource creation Initiated  
                                                              xxxxxx                                                   
CREATE_COMPLETE                AWS::ApiGateway::Deployment    ServerlessRestApiDeployment4   -                            
                                                              xxxxxx                                                   
CREATE_IN_PROGRESS             AWS::ApiGateway::Stage         ServerlessRestApiProdStage     -                            
CREATE_IN_PROGRESS             AWS::ApiGateway::Stage         ServerlessRestApiProdStage     Resource creation Initiated  
CREATE_COMPLETE                AWS::ApiGateway::Stage         ServerlessRestApiProdStage     -                            
CREATE_COMPLETE                AWS::CloudFormation::Stack     aws-test-sam-sample            -                            
-------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - aws-test-sam-sample in ap-northeast-1

正常にデプロイされると、こちらのようにLambda関数が作成されます。

created_lambda_function

API Gatewayも作成されます。

created_api_gateway

裏ではAWS CloudFormationのスタックが作成されています。

created_cfn_stack

LambdaのコンソールからURLを確認し、<エンドポイント>/Prod/helloでブラウザからアクセスすると、ローカルで検証した時と同じレスポンスを返す動作を確認できます。

スクリーンショット 2024-08-13 12.41.45

SAMは、サーバーレスアプリケーションもデプロイできる拡張版CFn

テンプレートの基本的な書き方はCFnとほぼ同じですので、普段からCFnを使用しているユーザーなら、その延長線上で簡単にデプロイできる印象です。

SAMでlambdaなどをデプロイする時は、SAM CLIによるビルドからデプロイまでの一連の流れなどを把握しておきましょう。では!

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.